#include "StdAfx.h"
#include "ConfigManage.h"
#include "ParseConfig.h"
#include "Task.h"
#include "unzip.h"
#include <shlwapi.h>

#define MATERIAL_NAME   _T("material")
#define UNZIP_MATERIAL_NAME   _T("material_unzip")
//#include "..\StormWidgetUILibrary\StdString.h"

CConfigManage::CConfigManage(void):
m_pParseConfig(NULL),
m_pSetupThread(NULL),
m_pTaskEvent(NULL),
m_pDownloadConfig(NULL),
m_nConfigTaskID(0),
m_strConfigPath(L""),
m_pPostCount(NULL)
//m_nNodeCount(0)
{
}

CConfigManage::~CConfigManage(void)
{
	StopSetupThread();
	if(m_pTaskList.size() > 0)
	{
		ITask* pTask = NULL;
		FOREACH_TASK_BEGIN(pTask)
		{
			if(pTask)
				delete pTask;
		}
		FOREACH_TASK_END()
	}
	m_pTaskList.clear();

	if(m_vNodeList.size() > 0)
		m_vNodeList.clear();

	if(m_pDownloadConfig)
		delete m_pDownloadConfig;
	if(m_pPostCount)
		delete m_pPostCount;
}

void CConfigManage::StartSetupThread()
{
	if(NULL == m_pSetupThread)
	{
		m_pSetupThread = new CSetupThread;
		m_pSetupThread->Start(m_pTaskEvent,m_pPostCount);
	}
	else
	{
		Resume();
	}
}

void CConfigManage::StopSetupThread()
{
	if(m_pSetupThread)
	{
		m_pSetupThread->Cancel();
		delete m_pSetupThread;
		m_pSetupThread = NULL;
	}
}

void CConfigManage::StartPostCount()
{
	if(!m_pPostCount)
	{
		m_pPostCount = new CPostCount;
		m_pPostCount->Create();
	}
}

void CConfigManage::PostCount(LPCTSTR pstrUrl)
{
	if(m_pPostCount)
	{
		m_pPostCount->AddPostCount(pstrUrl);
	}
}

UINT CConfigManage::GetTaskCount()
{
	return m_pTaskList.size();
}

UINT CConfigManage::GetNodeCount()
{
	return m_vNodeList.size();
}

UINT CConfigManage::GetTypeCount()
{
	//MessageBox(NULL,L"GetTypeCount",L"GetTypeCount",MB_OK);
	if(m_pParseConfig)
	{
		
		UINT i = m_pParseConfig->GetTypeCount(m_strConfigPath);
		TCHAR sz[MAX_PATH];
		memset(sz,0x0,MAX_PATH);
		_sntprintf(sz,MAX_PATH,L"%d",i);
		//MessageBox(NULL,sz,L"GetTypeCount",MB_OK);
		return  i;
	}
	return 0;
}

LPCTSTR CConfigManage::GetTypeName(UINT nIndex)
{
	CStdString strTypeName = L"";
	if(m_pParseConfig)
		strTypeName = m_pParseConfig->GetTypeName(nIndex);
	return strTypeName;
}

UINT CConfigManage::GetShowNodeByTypeName(LPCTSTR pstrTypeName)
{
	if(m_pParseConfig)
		return m_pParseConfig->GetTypeShowNode(pstrTypeName);
	return 0;
}

BOOL CConfigManage::Load(LPCTSTR lpConfigPath)
{
	m_strConfigPath = lpConfigPath;

	m_pParseConfig = new CParseConfig;
	_ASSERT(m_pParseConfig);
	if(m_pParseConfig)
	{
		UINT nTypeCount = m_pParseConfig->GetTypeCount(lpConfigPath);
		for(int i = 0;i < nTypeCount;i++)
		{
			CStdString strTypeName = m_pParseConfig->GetTypeName(i);
			//int n = m_pParseConfig->GetTypeShowNode(strTypeName);
			int n = m_pParseConfig->GetNodeContByType(lpConfigPath,strTypeName);
			for(int j = 0;j < n;j++)
			{
				CMaterialInfo nInfo;
				if(m_pParseConfig->GetNodeInfomation(m_strConfigPath,j,strTypeName,nInfo) == TRUE)
				{
					if(nInfo.m_strRegeditKey != L"" && nInfo.m_strRegeditPath != L"")
					{
						nInfo.m_strState = GetStateByRegedit(nInfo.m_strRegeditKey,nInfo.m_strRegeditPath,
							nInfo.m_strRegeditValue,nInfo.m_strState,nInfo.m_strVersion);
					}
					else
					{
						nInfo.m_strState = GetState(nInfo.m_strState,nInfo.m_strProcess,nInfo.m_strVersion);
					}
					nInfo.m_strIco = GetMaterialPath() + nInfo.m_strIco;
					m_vNodeList.push_back(nInfo);
				}
			}
		}
		
		if(m_vNodeList.size() > 0)
			return TRUE;
		

		/*UINT nNodeCount = m_pParseConfig->GetNodeCount(lpConfigPath);
		if(nNodeCount > 0)
		{
			for(UINT i = 0;i < nNodeCount;i++)
			{
				CMaterialInfo nInfo;
				if(m_pParseConfig->GetNodeInfomation(lpConfigPath,i,nInfo) == TRUE)
				{
					if(nInfo.m_strRegeditKey != L"" && nInfo.m_strRegeditPath != L"")
					{
						nInfo.m_strState = GetStateByRegedit(nInfo.m_strRegeditKey,nInfo.m_strRegeditPath,
							nInfo.m_strRegeditValue,nInfo.m_strState,nInfo.m_strVersion);
					}
					else
					{
						nInfo.m_strState = GetState(nInfo.m_strState,nInfo.m_strProcess,nInfo.m_strVersion);
					}
					nInfo.m_strIco = GetMaterialPath() + nInfo.m_strIco;
					m_vNodeList.push_back(nInfo);
				}
			}

			if(m_vNodeList.size() > 0)
				return TRUE;
		}*/
	}
	return FALSE;
}

CStdString CConfigManage::GetMaterialPath()
{
	TCHAR szPath[MAX_PATH] ={0};
	GetTempPath(MAX_PATH, szPath);
	PathAddBackslash(szPath);
	_tcscat(szPath,L"Storm\\");
	_tcscat(szPath,UNZIP_MATERIAL_NAME);
	_tcscat(szPath,L"\\");
	CStdString strTempPath = szPath;
	return strTempPath;
}

CStdString CConfigManage::GetTempStormPath()
{
	TCHAR szPath[MAX_PATH] ={0};
	GetTempPath(MAX_PATH, szPath);
	PathAddBackslash(szPath);
	_tcscat(szPath,L"Storm\\");
	CStdString strTempPath = szPath;
	return strTempPath;
}

void CConfigManage::AddNodeToTaskList()
{
	for(std::vector<CMaterialInfo>::iterator itor = m_vNodeList.begin();itor != m_vNodeList.end();++itor)
	{
		if((*itor).m_strSetup == L"1")
		{
			ITask* pTask = new CTask;
			_ASSERT(m_pParseConfig);
			pTask->SetTaskContent((*itor));
			m_pTaskList.push_back(pTask);
		}
		
	}
	
}

BOOL CConfigManage::RunTask(TASKTYPE nTaskType,UINT nTaskNo,ITaskEvent* pCallBack)
{
	_ASSERT(pCallBack);
	m_pTaskEvent = pCallBack;

	if(nTaskType == EXETASK)
	{
		StartPostCount();
		StartSetupThread();
	}
	
	if(nTaskNo < 0 || nTaskNo > m_pTaskList.size())
		return FALSE;
	ITask* pTask = NULL;
	pTask = m_pTaskList[nTaskNo];
	_ASSERT(pTask);
	if(pTask)
		pTask->Run(nTaskType,pCallBack,m_pSetupThread,m_pPostCount);
	return TRUE;
}

BOOL CConfigManage::Pause(UINT nTaskNo)
{
	if(m_pSetupThread)
		m_pSetupThread->Pause();
	if(nTaskNo < 0 || nTaskNo > m_pTaskList.size())
		return FALSE;
	ITask* pTask = NULL;
	pTask = m_pTaskList[nTaskNo];
	_ASSERT(pTask);
	if(pTask)
		pTask->Pause();
	return TRUE;
}

void CConfigManage::Resume()
{
	if(m_pSetupThread)
		m_pSetupThread->Resume();
}

BOOL CConfigManage::GetNodeInfo(UINT nIndex,CMaterialInfo& info)
{
	if(m_pParseConfig == NULL)
		return FALSE;
	if(nIndex < 0 || nIndex > m_vNodeList.size())
		return FALSE;
	info = m_vNodeList[nIndex];
	return TRUE;

}

BOOL CConfigManage::GetTaskInfo(UINT nIndex,CMaterialInfo& info)
{
	if(m_pParseConfig == NULL)
		return FALSE;
	if(nIndex < 0 || nIndex > m_pTaskList.size())
		return FALSE;
	info = m_pTaskList[nIndex]->GetTaskContext();
	return TRUE;
}

BOOL CConfigManage::SetupConfigInfomation(LPCTSTR pstrID)
{
	BOOL bRes = FALSE;
	//std::vector<CStdString> vSetupTaskNo;
	//vSetupTaskNo.push_back(pstrID);
	if(m_pParseConfig)
		bRes = m_pParseConfig->SetNodeAttribute(GetConfigPath(),pstrID,L"1");
		//bRes = m_pParseConfig->SetNodeAttribute(GetConfigPath(),vSetupTaskNo,L"1");
	return bRes;
}

LPCTSTR CConfigManage::GetNodeAttribute(int nIndex,LPCTSTR pstrName)
{
	if(m_vNodeList.size() <= 0 || nIndex < 0 || nIndex > m_vNodeList.size())
		return L"";
	CStdString strName = pstrName;
	CStdString strAttribute;
	CMaterialInfo info = m_vNodeList[nIndex];

	if(strName == MATERIAL_NODE_ATTRIBUTE_NAME)
		strAttribute = info.m_strName;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_ID)
		strAttribute = info.m_strID;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_TYPE)
		strAttribute = info.m_strType;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_ICO)
		strAttribute = info.m_strIco;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_PROCESS)
		strAttribute = info.m_strProcess;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_URL)
		strAttribute = info.m_strUrl;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_VERSION)
		strAttribute = info.m_strVersion;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_SIZE)
		strAttribute = info.m_strSize;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_MD5)
		strAttribute = info.m_strMD5;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_REMARK)
		strAttribute = info.m_strRemark;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_TIPS)
		strAttribute = info.m_strTips;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_REGEDITKEY)
		strAttribute = info.m_strRegeditKey;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_REGEDITPATH)
		strAttribute = info.m_strRegeditPath;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_REGEDITVALUE)
		strAttribute = info.m_strRegeditValue;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_SETUP)
		strAttribute = info.m_strSetup;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_STATE)
		strAttribute = info.m_strState;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_PERCENTAGE)
		strAttribute = info.m_strPercentage;
	else if(strName == MATERIAL_NODE_ATTRIBUTE_POS)
		strAttribute = info.m_strPos;
	else
		strAttribute = L"";

	return strAttribute.GetData();
}


/*UINT CConfigManage::SetConfigInfomation(LPCTSTR lpstrRemotePath)
{
	
	CStdString strStormTemp = GetTempStormPath();
	strStormTemp += UNZIP_MATERIAL_NAME;
	UINT nCount = 0;
	if(Unzip(lpstrRemotePath,strStormTemp.GetData(),TRUE))
	{
		strStormTemp += L"\\material.xml";
		if(Load(strStormTemp.GetData()) == TRUE)
		{
			nCount = GetNodeCount();
		}
	}
	return nCount;
}*/
/*void CConfigManage::DownloadConfigInfomation(IConfigManageCallBack* pCallBack,LPCTSTR lpstrRemotePath)
{
	TCHAR szID[MAX_PATH];
	memset(szID,0x0,MAX_PATH);
	_itow(m_nConfigTaskID,szID,10);
	m_nConfigTaskID++;
	//CStdString strPath;
	CMaterialInfo nInfo;
	nInfo.m_strID = szID;
	nInfo.m_strUrl = lpstrRemotePath;
	nInfo.m_strProcess = L"material";
	CStdString strMaterialZip = GetTempStormPath() + MATERIAL_NAME;
	SetFileAttributes(strMaterialZip,GetFileAttributes(strMaterialZip.GetData())&~FILE_ATTRIBUTE_READONLY);
	DeleteFile(strMaterialZip);
	if(m_pDownloadConfig == NULL)
	{
		//m_pDownloadConfig = new CDownloadConfig(this,m_nConfigTaskID,XML,pCallBack);
	}
	ITask* pTask = new CTask;
	_ASSERT(pTask);
	pTask->SetTaskContent(nInfo);
	m_pTaskList.push_back(pTask);
	_ASSERT(m_pDownloadConfig);
	RunTask(XML,0,m_pDownloadConfig);
	//m_pDownloadConfig->StartMessageLoop();

	//m_pDownloadConfig->StartDownload();
}*/

UINT CConfigManage::SetLocalConfigInfomation(LPCTSTR lpstrLocalPath)
{
	CStdString strStormTemp = GetTempStormPath();
	strStormTemp += UNZIP_MATERIAL_NAME;
	UINT nCount = 0;
	if(Unzip(lpstrLocalPath,strStormTemp.GetData(),FALSE))
	{
		strStormTemp += L"\\material.xml";
		if(Load(strStormTemp.GetData()) == TRUE)
		{
			nCount = GetNodeCount();
		}
	}
	return nCount;
}
void CConfigManage::SetConfigInfomation(IConfigManageCallBack* pCallBack,
										LPCTSTR lpstrLocalMaterialZipPath,
										LPCTSTR lpstrRemoteMaterialZipPath)
{
	TCHAR szID[MAX_PATH];
	memset(szID,0x0,MAX_PATH);
	_itow(m_nConfigTaskID,szID,10);
	m_nConfigTaskID++;
	//CStdString strPath;
	CMaterialInfo nInfo;
	nInfo.m_strID = szID;
	nInfo.m_strUrl = lpstrRemoteMaterialZipPath;
	nInfo.m_strProcess = L"material";
	CStdString strMaterialZip = GetTempStormPath() + MATERIAL_NAME;
	SetFileAttributes(strMaterialZip,GetFileAttributes(strMaterialZip.GetData())&~FILE_ATTRIBUTE_READONLY);
	DeleteFile(strMaterialZip);
	if(m_pDownloadConfig == NULL)
	{
		m_pDownloadConfig = new CDownloadConfig(this,m_nConfigTaskID,XML,pCallBack);
	}
	ITask* pTask = new CTask;
	_ASSERT(pTask);
	pTask->SetTaskContent(nInfo);
	m_pTaskList.push_back(pTask);
	_ASSERT(m_pDownloadConfig);
	m_pDownloadConfig->SetLocalMaterialZipPath(lpstrLocalMaterialZipPath);
	RunTask(XML,0,m_pDownloadConfig);
}

BOOL CConfigManage::UnzipTask(int nTaskNo)
{
	if(nTaskNo < 0 || nTaskNo > m_pTaskList.size())
		return FALSE;

	TCHAR szPath[MAX_PATH] ={0};
	GetTempPath(MAX_PATH, szPath);
	PathAddBackslash(szPath);
	_tcscat(szPath,L"Storm\\");
	CStdString strDiskPath = szPath;
	CStdString strSourcePath = strDiskPath + MATERIAL_NAME;
	CStdString strUnzipPath = szPath;
	strUnzipPath += UNZIP_MATERIAL_NAME;
	return Unzip(strSourcePath.GetData(),strUnzipPath.GetData(),FALSE);

}

BOOL CConfigManage::Unzip(LPCTSTR lpZip,LPCTSTR lpPath,BOOL bDelZip)
{

	ZRESULT zr;
	ZIPENTRY ze;
	HZIP hz = 0;
	LPTSTR lpCpyFilePos = NULL;
	TCHAR unZipFile[MAX_PATH];
	int len = lstrlen(lpPath);
	if(len)
	{
		StrCpy(unZipFile,lpPath);
		TCHAR lastChar = unZipFile[len-1];
		if(lastChar!='\\')
		{
			StrCat(unZipFile,_T("\\"));
		}
		lpCpyFilePos = &unZipFile[lstrlen(unZipFile)];
	}
	else
	{
		lpCpyFilePos = unZipFile;
	}
	do 
	{
		hz=OpenZip(lpZip,0);
		if( hz==0 )
			break;

		zr=GetZipItem(hz,-1,&ze);
		if (zr!=ZR_OK) 
			break ;
		int nCount = ze.index;

		for(int i=0;i<nCount;i++)
		{
			zr=GetZipItem(hz,i,&ze);
			if (zr!=ZR_OK) 
				break ;

			StrCpy(lpCpyFilePos,ze.name);

			SetFileAttributes(unZipFile,~FILE_ATTRIBUTE_READONLY&GetFileAttributes(unZipFile));
			DeleteFile(unZipFile);

			zr=UnzipItem(hz,i,unZipFile);

			if (zr!=ZR_OK) 
				break ;
		}
		if (zr!=ZR_OK) 
			break ;

		zr=CloseZip(hz);
		if (zr!=ZR_OK) 
			break;

		if(bDelZip)
			DeleteFile(lpZip);

		hz = 0;
	} while(0);

	if(hz)
	{
		CloseZip(hz);
	}
	if(zr!=ZR_OK)
		return FALSE;

	return TRUE;
}

CStdString CConfigManage::GetConfigPath()
{
	return m_strConfigPath;
}

UINT CConfigManage::CompareExeVersion(CStdString strCurrent,CStdString strNew)
{
	//CStdString strFiltered = strCurrent.Replace(L".",L"");
	//UINT nCurrent = _wtoi(strFiltered.GetData());
	//if(nCurrent - nNew >= 0)
		//return 1;
	//else if(nCurrent - nNew < 0)
		//return -1;
	if(strCurrent == strNew)
		return 1;
	else
		return 0;
}

CStdString CConfigManage::GetState(CStdString strCurrentStat,CStdString strProcessName,CStdString strCurrentVersion)
{
	CStdString strRes = strCurrentStat;
	CStdString strReturnCurrentVersion;
	if(m_EnumRegedit.FindVersion(strProcessName.GetData(),strReturnCurrentVersion) == TRUE)
	{
		UINT nRes  = CompareExeVersion(strCurrentVersion,strReturnCurrentVersion);
		if(nRes > 0)
			strRes = WU_CHECKSETUPSTATE_SETUPED;
		else
			strRes = WU_CHECKSETUPSTATE_UPDATE;
	}
	return strRes;
}

CStdString CConfigManage::GetStateByRegedit(CStdString strKey,CStdString strPath,CStdString strValue,
							 CStdString strCurrentStat,CStdString strCurrentVersion)
{
	CStdString strRes = strCurrentStat;
	//UINT nCurrentVersion;
	CStdString strLocalVersion;

	if(m_EnumRegedit.FindVersionByKey(strKey,strPath,strValue,strLocalVersion) == TRUE)
	{
		UINT nRes  = CompareExeVersion(strCurrentVersion,strLocalVersion);
		if(nRes > 0)
			strRes = WU_CHECKSETUPSTATE_SETUPED;
		else
			strRes = WU_CHECKSETUPSTATE_UPDATE;
	}
	return strRes;
}


extern "C" HRESULT WINAPI CreateConfigManage(HINSTANCE hInst,HWND hWndParent,IConfigManage** ppConfigManage)
{
	*ppConfigManage = new CConfigManage;
	return *ppConfigManage ? S_OK : E_FAIL;
}

